/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package GUI;

import Interfaces.Diaxeirish;
import Interfaces.ApparentModalI;
import Model.Album;
import Model.Albumtype;
import Model.Artist;
import Model.Musicgroup;
import Model.Musicproductioncompany;
import Model.Song;
import static java.awt.Color.red;
import java.awt.Frame;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import static java.awt.event.KeyEvent.VK_ENTER;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.EventObject;
import java.util.Hashtable;
import java.util.List;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.DefaultCellEditor;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.KeyStroke;
import javax.swing.border.TitledBorder;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import src.General;
import src.MaxLenNoDupSongDefaultCellEditor;
import src.PositiveIntDefaultCellEditor;
import src.PositiveIntInputVerifier;
import src.SimpleDateFormatInputVerifier;
import src.TextMaxLengthTrimInputVerifier;

/**
 * Διαχείριση άλμπουμ (καλλιτέχνη ή συγκροτήματος κατά περίσταση)
 *
 */
public final class ManageAlbumTableJFrame extends javax.swing.JFrame implements Diaxeirish, ApparentModalI {

    AlbumTableJFrame caller;
    private Album album;//για περίπτωση διαχείρισης ActionType.Update παίρνει αντίγραφο του επιλεγμένου γκρουπ του πίνακα της καλούσας φόρμας και δεν γίνεται ποτέ managed. Χρησιμοποιείται η μέθοδος merge του entity manager
    private General.ActionType actionType;
    private final JFrame next = null;
    private List<Song> songList;
    private final List<Song> oldSongList;
    private final JTextField jt = new JTextField();

    /**
     * Creates new form ManageArtistsAlbumTableJFrame
     */
    public ManageAlbumTableJFrame() {
        throw new UnsupportedOperationException();

    }

    /**
     * Constructor overload
     *
     * @param caller
     */
    public ManageAlbumTableJFrame(AlbumTableJFrame caller, List<Song> oldSongList, General.ActionType at) throws IOException, ClassNotFoundException {
        initComponents();

        try {
            General.setWindowImage(this);
        } catch (Exception ex) {
        }
        this.caller = caller;
        if (!this.caller.getIsArtistAlbum()) {
            org.jdesktop.swingbinding.SwingBindings.createJComboBoxBinding(org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ_WRITE, musicgroupList, jComboBox3).bind();
            this.setTitle("Διαχείριση άλμπουμ μουσικού συγκροτήματος");
            ((TitledBorder) this.jPanel1.getBorder()).setTitle("Στοιχεία άλμπουμ μουσικού συγκροτήματος");
            jLabel7.setText("Συγκρότημα");
        } else {
            org.jdesktop.swingbinding.SwingBindings.createJComboBoxBinding(org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ_WRITE, artistList, jComboBox3).bind();
        }
        this.oldSongList = oldSongList;
        this.actionType = at;
        //Ανάλογα με την περίπτωση διαχείρισης
        switch (actionType) {
            case Insert:
                this.setTitle(this.getTitle() + " - " + "Εισαγωγή");
                this.savejButton2.setText("Αποθήκευση");
                this.jComboBox1.setSelectedIndex(-1);
                this.jComboBox2.setSelectedIndex(-1);
                this.jComboBox3.setSelectedIndex(-1);
                this.jButton3.setEnabled(false);
                this.album = this.caller.getSelectedEntityClone();
                this.songList = this.album.getSongList();
                this.songList = this.bindTableToObservableSongList(this.songList, jTable1);
                setJTableListeners(jt);
                break;
            case Update:
                this.setTitle(this.getTitle() + " - " + "Μεταβολή");
                this.savejButton2.setText("Μεταβολή");
                this.album = this.caller.getSelectedEntityClone();
                this.songList = this.album.getSongList();
                this.songList = this.bindTableToObservableSongList(this.songList, jTable1);
                this.setFormData();
                setJTableListeners(jt);
                break;
            case Delete:
                this.setTitle(this.getTitle() + " - " + "Διαγραφή !");
                this.savejButton2.setText("Διαγραφή");
                this.album = this.caller.getSelectedEntityClone();
                this.songList = this.album.getSongList();
                this.songList = this.bindTableToObservableSongList(this.songList, jTable1);
                this.setFormData();
                General.disableAllComponents(this.jPanel1);
                General.disableAllComponents(this.jPanel2);
                //Δεν επιτρέπει εισαγωγή δεδομένων στο jtable
                DefaultCellEditor notEditable = new DefaultCellEditor(new JTextField()) {
                    @Override
                    public boolean isCellEditable(EventObject anEvent) {
                        return false;
                    }
                };
                for (int i = 0; i < this.jTable1.getColumnModel().getColumnCount(); i++) {
                    this.jTable1.getColumnModel().getColumn(i).setCellEditor(notEditable);
                }
                break;
            default:
                break;
        }
        jTable1.getTableHeader().setReorderingAllowed(false);
        jTable1.getRowSorter().toggleSortOrder(0);
        //input verifiers για τα textfields
        this.albumTitlejTextField1.setInputVerifier(new TextMaxLengthTrimInputVerifier(titlosValidationJLabel, 50));
        this.diskNumberjTextField3.setInputVerifier(new PositiveIntInputVerifier(diskNumValidationJLabel));
        this.releaseDateTextField.setInputVerifier(new SimpleDateFormatInputVerifier(releaseDateValidationJLabel));
    }

    private void setJTableListeners(JTextField jt) {
        //Θέτει custom cell editors για τον πίνακα
        this.jTable1.getColumnModel().getColumn(1).setCellEditor(new MaxLenNoDupSongDefaultCellEditor(jt, this.jLabel1, 50, this.jTable1, 1, this.songList));
        this.jTable1.getColumnModel().getColumn(0).setCellEditor(new PositiveIntDefaultCellEditor(jt, this.jLabel1, jTable1, 0));
        this.jTable1.getColumnModel().getColumn(2).setCellEditor(new PositiveIntDefaultCellEditor(jt, this.jLabel1, this.jTable1, 2));
        Hashtable columnHint = new Hashtable();
        columnHint.put(0, "Ακέραιος αριθμός μεγαλύτερος του 0");
        columnHint.put(1, "Μέχρι 50 χαρακτήρες, μοναδικό");
        columnHint.put(2, "Ακέραιος αριθμός μεγαλύτερος του 0");
        //Υπόδειξη ανάλογα με το επιλεγμένο πεδίο
        this.jTable1.getColumnModel().getSelectionModel().addListSelectionListener(new ListSelectionListener() {
            @Override
            public void valueChanged(ListSelectionEvent e) {
                if (!jLabel1.getForeground().equals(red) && jTable1.getSelectedColumn() > -1) {
                    jLabel1.setText(columnHint.get(jTable1.getSelectedColumn()).toString());
                }
            }
        });
        this.jTable1.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
            @Override
            public void valueChanged(ListSelectionEvent e) {
                if (!jLabel1.getForeground().equals(red) && jTable1.getSelectedColumn() > -1) {
                    jLabel1.setText(columnHint.get(jTable1.getSelectedColumn()).toString());
                }
            }
        });

        //Ενεργοποιεί το event cancelCellEditing του MaxLenDefaultCellEditor κατά την ακύρωση με esc
        Action escCancel = new AbstractAction() {
            public void actionPerformed(ActionEvent e) {
                if (jTable1.isEditing()) {
                    jTable1.getCellEditor(jTable1.getEditingRow(), jTable1.getEditingColumn()).cancelCellEditing();
                    switch (jTable1.getSelectedColumn()) {
                        case 0:
                            jLabel1.setText("Ακέραιος αριθμός μεγαλύτερος του 0");
                            break;
                        case 1:
                            jLabel1.setText("Μέχρι 50 χαρακτήρες, μοναδικό");
                            break;
                        case 2:
                            jLabel1.setText("Ακέραιος αριθμός μεγαλύτερος του 0");
                            break;
                        default:
                            break;
                    }
                }
            }
        };
        jTable1.getInputMap(JTable.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0, false), "ESCAPE");
        jTable1.getActionMap().put("ESCAPE", escCancel);
    }

    private int getNextTrackNum() {
        int max = 0;
        for (Song s : songList) {
            if (s.getTrackNumber() > max) {
                max = s.getTrackNumber();
            }
        }
        return max + 1;
    }

    private List<Song> bindTableToObservableSongList(List<Song> songList, JTable jt) {

        songList = (List<Song>) org.jdesktop.observablecollections.ObservableCollections.observableList(songList);
        org.jdesktop.swingbinding.JTableBinding jTableBinding = org.jdesktop.swingbinding.SwingBindings.createJTableBinding(org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ_WRITE, songList, this.jTable1);
        org.jdesktop.swingbinding.JTableBinding.ColumnBinding columnBinding = jTableBinding.addColumnBinding(org.jdesktop.beansbinding.ELProperty.create("${trackNumber}"));
        columnBinding.setColumnName("Αριθμός σειράς");
        columnBinding.setColumnClass(Integer.class);
        columnBinding = jTableBinding.addColumnBinding(org.jdesktop.beansbinding.ELProperty.create("${songTitle}"));
        columnBinding.setColumnName("Τίτλος");
        columnBinding.setColumnClass(String.class);
        columnBinding = jTableBinding.addColumnBinding(org.jdesktop.beansbinding.ELProperty.create("${duration}"));
        columnBinding.setColumnName("Διάρκεια(δευτερόλεπτα)");
        columnBinding.setColumnClass(Integer.class);
        jTableBinding.bind();
        return songList;
    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {
        bindingGroup = new org.jdesktop.beansbinding.BindingGroup();

        RadioStationPUEntityManager = java.beans.Beans.isDesignTime() ? null : javax.persistence.Persistence.createEntityManagerFactory("RadioStationPU").createEntityManager();
        albumtypeQuery = java.beans.Beans.isDesignTime() ? null : RadioStationPUEntityManager.createQuery("SELECT a FROM Albumtype a");
        albumtypeList = java.beans.Beans.isDesignTime() ? java.util.Collections.emptyList() : albumtypeQuery.getResultList();
        musicproductioncompanyQuery = java.beans.Beans.isDesignTime() ? null : RadioStationPUEntityManager.createQuery("SELECT m FROM Musicproductioncompany m");
        musicproductioncompanyList = java.beans.Beans.isDesignTime() ? java.util.Collections.emptyList() : musicproductioncompanyQuery.getResultList();
        artistQuery = java.beans.Beans.isDesignTime() ? null : RadioStationPUEntityManager.createQuery("SELECT a FROM Artist a");
        artistList = java.beans.Beans.isDesignTime() ? java.util.Collections.emptyList() : artistQuery.getResultList();
        musicgroupQuery = java.beans.Beans.isDesignTime() ? null : RadioStationPUEntityManager.createQuery("SELECT m FROM Musicgroup m");
        musicgroupList = java.beans.Beans.isDesignTime() ? java.util.Collections.emptyList() : musicgroupQuery.getResultList();
        jPanel1 = new javax.swing.JPanel();
        jLabel2 = new javax.swing.JLabel();
        jLabel3 = new javax.swing.JLabel();
        albumTitlejTextField1 = new javax.swing.JTextField();
        diskNumberjTextField3 = new javax.swing.JTextField();
        jLabel4 = new javax.swing.JLabel();
        jLabel5 = new javax.swing.JLabel();
        jLabel6 = new javax.swing.JLabel();
        jLabel7 = new javax.swing.JLabel();
        releaseDateTextField = new javax.swing.JTextField();
        jComboBox1 = new javax.swing.JComboBox();
        jComboBox2 = new javax.swing.JComboBox();
        jComboBox3 = new javax.swing.JComboBox();
        jPanel2 = new javax.swing.JPanel();
        jLabel8 = new javax.swing.JLabel();
        jButton2 = new javax.swing.JButton();
        jScrollPane2 = new javax.swing.JScrollPane();
        jTable1 = new javax.swing.JTable();
        jButton3 = new javax.swing.JButton();
        jPanel3 = new javax.swing.JPanel();
        jLabel1 = new javax.swing.JLabel();
        titlosValidationJLabel = new javax.swing.JLabel();
        diskNumValidationJLabel = new javax.swing.JLabel();
        releaseDateValidationJLabel = new javax.swing.JLabel();
        savejButton2 = new javax.swing.JButton();
        canceljButton1 = new javax.swing.JButton();

        setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
        setTitle("Διαχείριση άλμπουμ καλλιτέχνη");
        setLocationByPlatform(true);
        setMinimumSize(new java.awt.Dimension(756, 505));

        jPanel1.setBorder(javax.swing.BorderFactory.createTitledBorder("Στοιχεία άλμπουμ καλλιτέχνη"));

        jLabel2.setText("Τίτλος Άλμπουμ");

        jLabel3.setText("Τύπος Άλμπουμ");

        albumTitlejTextField1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                albumTitlejTextField1ActionPerformed(evt);
            }
        });
        albumTitlejTextField1.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyPressed(java.awt.event.KeyEvent evt) {
                albumTitlejTextField1KeyPressed(evt);
            }
        });

        diskNumberjTextField3.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyPressed(java.awt.event.KeyEvent evt) {
                diskNumberjTextField3KeyPressed(evt);
            }
        });

        jLabel4.setText("Αριθμός Άλμπουμ");

        jLabel5.setText("Εταιρεία Παραγωγής");

        jLabel6.setText("Ημερομηνία Κυκλοφορίας");

        jLabel7.setText("Καλλιτέχνης");

        releaseDateTextField.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyPressed(java.awt.event.KeyEvent evt) {
                releaseDateTextFieldKeyPressed(evt);
            }
        });

        org.jdesktop.swingbinding.JComboBoxBinding jComboBoxBinding = org.jdesktop.swingbinding.SwingBindings.createJComboBoxBinding(org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ_WRITE, albumtypeList, jComboBox1);
        bindingGroup.addBinding(jComboBoxBinding);

        jComboBox1.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyPressed(java.awt.event.KeyEvent evt) {
                jComboBox1KeyPressed(evt);
            }
        });

        jComboBoxBinding = org.jdesktop.swingbinding.SwingBindings.createJComboBoxBinding(org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ_WRITE, musicproductioncompanyList, jComboBox2);
        bindingGroup.addBinding(jComboBoxBinding);

        jComboBox2.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyPressed(java.awt.event.KeyEvent evt) {
                jComboBox2KeyPressed(evt);
            }
        });

        jComboBox3.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyPressed(java.awt.event.KeyEvent evt) {
                jComboBox3KeyPressed(evt);
            }
        });

        jPanel2.setBorder(javax.swing.BorderFactory.createEtchedBorder());

        jLabel8.setText("Λίστα Τραγουδιών");

        jButton2.setText("Εισαγωγή");
        jButton2.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton2ActionPerformed(evt);
            }
        });

        jTable1.setAutoCreateRowSorter(true);
        jTable1.setCellSelectionEnabled(true);
        jTable1.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
        jTable1.addComponentListener(new java.awt.event.ComponentAdapter() {
            public void componentResized(java.awt.event.ComponentEvent evt) {
                jTable1ComponentResized(evt);
            }
        });
        jScrollPane2.setViewportView(jTable1);

        jButton3.setText("Διαγραφή");
        jButton3.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton3ActionPerformed(evt);
            }
        });

        jPanel3.setBorder(javax.swing.BorderFactory.createBevelBorder(javax.swing.border.BevelBorder.RAISED));

        javax.swing.GroupLayout jPanel3Layout = new javax.swing.GroupLayout(jPanel3);
        jPanel3.setLayout(jPanel3Layout);
        jPanel3Layout.setHorizontalGroup(
            jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel3Layout.createSequentialGroup()
                .addComponent(jLabel1)
                .addGap(0, 0, Short.MAX_VALUE))
        );
        jPanel3Layout.setVerticalGroup(
            jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jLabel1, javax.swing.GroupLayout.DEFAULT_SIZE, 19, Short.MAX_VALUE)
        );

        javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2);
        jPanel2.setLayout(jPanel2Layout);
        jPanel2Layout.setHorizontalGroup(
            jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel2Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jPanel3, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addGroup(jPanel2Layout.createSequentialGroup()
                        .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(jLabel8)
                            .addGroup(jPanel2Layout.createSequentialGroup()
                                .addComponent(jButton2)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addComponent(jButton3)))
                        .addGap(0, 0, Short.MAX_VALUE))
                    .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 668, Short.MAX_VALUE))
                .addContainerGap())
        );
        jPanel2Layout.setVerticalGroup(
            jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel2Layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jLabel8)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 90, Short.MAX_VALUE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jPanel3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jButton3)
                    .addComponent(jButton2))
                .addContainerGap())
        );

        titlosValidationJLabel.setText("(μέχρι 255 χαρακτήρες)");

        diskNumValidationJLabel.setText("(Ακέραιος μεγαλύτερος από 0)");

        releaseDateValidationJLabel.setText("πχ 23/9/2014 (4 ψηφία για το έτος)");
        releaseDateValidationJLabel.setToolTipText("");
        releaseDateValidationJLabel.setAutoscrolls(true);

        javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
        jPanel1.setLayout(jPanel1Layout);
        jPanel1Layout.setHorizontalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                    .addComponent(jPanel2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addGroup(javax.swing.GroupLayout.Alignment.LEADING, jPanel1Layout.createSequentialGroup()
                        .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
                            .addGroup(javax.swing.GroupLayout.Alignment.LEADING, jPanel1Layout.createSequentialGroup()
                                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                                    .addComponent(jLabel4)
                                    .addComponent(jLabel2)
                                    .addComponent(jLabel3)
                                    .addComponent(jLabel5, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                                    .addComponent(jLabel7, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                    .addGroup(jPanel1Layout.createSequentialGroup()
                                        .addGap(33, 33, 33)
                                        .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                            .addComponent(diskNumberjTextField3, javax.swing.GroupLayout.PREFERRED_SIZE, 300, javax.swing.GroupLayout.PREFERRED_SIZE)
                                            .addComponent(jComboBox3, javax.swing.GroupLayout.PREFERRED_SIZE, 300, javax.swing.GroupLayout.PREFERRED_SIZE)
                                            .addComponent(jComboBox2, javax.swing.GroupLayout.PREFERRED_SIZE, 300, javax.swing.GroupLayout.PREFERRED_SIZE)))
                                    .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
                                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                        .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                            .addComponent(albumTitlejTextField1, javax.swing.GroupLayout.PREFERRED_SIZE, 300, javax.swing.GroupLayout.PREFERRED_SIZE)
                                            .addComponent(jComboBox1, javax.swing.GroupLayout.PREFERRED_SIZE, 300, javax.swing.GroupLayout.PREFERRED_SIZE)))))
                            .addGroup(javax.swing.GroupLayout.Alignment.LEADING, jPanel1Layout.createSequentialGroup()
                                .addComponent(jLabel6)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addComponent(releaseDateTextField)))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(diskNumValidationJLabel)
                            .addComponent(titlosValidationJLabel)
                            .addComponent(releaseDateValidationJLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 228, javax.swing.GroupLayout.PREFERRED_SIZE))))
                .addContainerGap())
        );
        jPanel1Layout.setVerticalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel1Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel2)
                    .addComponent(albumTitlejTextField1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(titlosValidationJLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addGap(12, 12, 12)
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel3)
                    .addComponent(jComboBox1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jLabel5)
                    .addComponent(jComboBox2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(jPanel1Layout.createSequentialGroup()
                        .addGap(12, 12, 12)
                        .addComponent(jLabel4))
                    .addGroup(jPanel1Layout.createSequentialGroup()
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                            .addComponent(diskNumberjTextField3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addComponent(diskNumValidationJLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE))))
                .addGap(9, 9, 9)
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel7)
                    .addComponent(jComboBox3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel6)
                    .addComponent(releaseDateTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(releaseDateValidationJLabel))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(jPanel2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

        savejButton2.setText("Αποθήκευση");
        savejButton2.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                savejButton2ActionPerformed(evt);
            }
        });

        canceljButton1.setText("Ακύρωση");
        canceljButton1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                canceljButton1ActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                        .addGap(0, 0, Short.MAX_VALUE)
                        .addComponent(savejButton2)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(canceljButton1, javax.swing.GroupLayout.PREFERRED_SIZE, 94, javax.swing.GroupLayout.PREFERRED_SIZE)))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(savejButton2)
                    .addComponent(canceljButton1))
                .addContainerGap())
        );

        bindingGroup.bind();

        pack();
        setLocationRelativeTo(null);
    }// </editor-fold>//GEN-END:initComponents

    private void albumTitlejTextField1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_albumTitlejTextField1ActionPerformed
        // TODO add your handling code here:
    }//GEN-LAST:event_albumTitlejTextField1ActionPerformed

    private void canceljButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_canceljButton1ActionPerformed
        General.closeWindowX(this);
    }//GEN-LAST:event_canceljButton1ActionPerformed

    private void jButton3ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton3ActionPerformed
        if (!General.checkRowSelected(jTable1, "τραγούδι", "τραγούδι", this)) {
            return;
        }
        int selectedSongIndex = General.getSelectedRowModelIndex(jTable1);
        this.songList.remove(selectedSongIndex);
        this.jLabel1.setText(General.Empty);
        if (this.songList.isEmpty()) {
            this.jButton3.setEnabled(false);
        }
    }//GEN-LAST:event_jButton3ActionPerformed

    private boolean tableValidationCheck() {
        for (int i = 0; i < this.jTable1.getColumnModel().getColumnCount(); i++) {
            if (!this.jTable1.getColumnModel().getColumn(i).getCellEditor().stopCellEditing()) {
                General.showWarningMessage("Τα δεδομένα που εισάγατε δεν είναι αποδεκτά.", "Έλεγχος ορθότητας δεδομένων", this);
                this.jt.requestFocus();
                return false;
            }
        }
        return true;
    }

    private void jTable1ComponentResized(java.awt.event.ComponentEvent evt) {//GEN-FIRST:event_jTable1ComponentResized

    }//GEN-LAST:event_jTable1ComponentResized


    private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton2ActionPerformed
        if (!tableValidationCheck()) {
            return;
        }
        int nextTrackNum = this.getNextTrackNum();
        Song newSong = new Song();
        newSong.setTrackNumber(nextTrackNum);
        newSong.setDuration(300);
        newSong.setSongTitle(General.Empty);
        newSong.setAlbumId(this.album);
        this.songList.add(newSong);
        General.selectModelCellNVisible(this.songList.size() - 1, 0, jTable1);
        this.jTable1.editCellAt(this.jTable1.convertRowIndexToView(this.songList.size() - 1), 0);
        this.jt.requestFocus();
        this.jButton3.setEnabled(true);
    }//GEN-LAST:event_jButton2ActionPerformed

    private void savejButton2ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_savejButton2ActionPerformed
        try {
            if (this.actionType != General.ActionType.Delete) {
                if (!General.checkJTFieldsInputVerification(this.jPanel1, this.getTitle(), this)) {
                    return;
                }
                if (!tableValidationCheck()) {
                    return;
                }
                try {
                    String artistOrGroup;
                    if (this.caller.getIsArtistAlbum()) {
                        artistOrGroup = "Καλλιτέχνης";
                    } else {
                        artistOrGroup = "Μουσικό συγκρότητμα";
                    }
                    if (!General.checkNotNulls(new Object[]{"Τίτλος άλμπουμ", "Τύπος άλμπουμ", "Εταιρεία παραγωγής", "Αριθμός άλμπουμ",
                        artistOrGroup, "Ημερομηνία κυκλοφορίας"}, new JComponent[]{this.albumTitlejTextField1, this.jComboBox1,
                        this.jComboBox2, this.diskNumberjTextField3, this.jComboBox3, this.releaseDateTextField}, this)) {
                        return;
                    }
                } catch (Exception ex) {
                    General.showErrorMessage(ex.getMessage(), "Error", this);
                    return;
                }
                int index;
                for (Song s : songList) {
                    if (s.getSongTitle() == null || s.getSongTitle().equals(General.Empty)) {
                        General.showWarningMessage("Το πεδίο 'Τίτλος' του πίνακα τραγουδιών είναι απαραίτητο.", "Έλεγχος απαραίτητων πεδίων", this);
                        index = General.songIndexOfByTitleNotCaseSensitive(songList, General.Empty);
                        General.selectModelCellNVisible(this.jTable1.convertRowIndexToView(index), 1, jTable1);
                        this.jTable1.editCellAt(this.jTable1.convertRowIndexToView(index), 1);
                        this.jt.requestFocus();
                        return;
                    }
                }
                if (this.songList.size() < 1) {
                    String artistOrGroup;
                    if (this.caller.getIsArtistAlbum()) {
                        artistOrGroup = "καλλιτέχνη";
                    } else {
                        artistOrGroup = "μουσικού συγκροτήματος";
                    }
                    General.showWarningMessage("Ένα άλμπουμ " + artistOrGroup + " πρέπει να έχει τουλάχιστον 1 τραγούδι.", "Έλεγχος πλήθους τραγουδιών", this);
                    return;
                }
            }
            switch (this.actionType) {
                case Delete:
                    try {
                        General.deleteFromDB(this.album.getAlbumId(), this.album, this.caller.getEM());
                        this.caller.getEntityList().remove(this.album);
                    } catch (Exception ex) {
                        General.safeRollback(this.caller.getEM());
                        General.showDbErrorMsgIf(ex, this);
                        return;
                    }
                    this.caller.getEntityList().remove(this.album);
                    break;
                case Insert:
                    try {
                        if (!this.setEntiyFromFormData()) {
                            return;
                        }
                        General.setCreated(this.songList);
                        General.insertToDB(this.album, this.caller.getEM());
                        this.caller.getEntityList().add(this.album);
                        int index = this.caller.getEntityList().indexOf(this.album);
                        General.selectModelRowNVisible(index, this.caller.getTable());
                    } catch (Exception ex) {
                        General.safeRollback(this.caller.getEM());
                        General.showDbErrorMsgIf(ex, this);
                        return;
                    }
                    break;
                case Update:
                    try {
                        if (!this.setEntiyFromFormData()) {
                            return;
                        }
                        //Εάν διαγράφτηκε ένα τραγούδι και μετά ξαναπροστέθηκε,τότε με κριτήτριο unique index (song title)
                        //δίνουμε στην καινούργια εγγραφή το musicSongId της παλιάς αφού στην ουσία πρόκειται για την ίδια
                        //εγγραφή, και έτσι αποφεύγουμε και exception για duplicate key value...
                        Song s2;
                        for (Song s : this.songList) {
                            if ((s2 = General.songGetByTitleNotCaseSensitive(this.oldSongList, s.getSongTitle())) != null) {
                                s.setSongId(s2.getSongId());
                                s.setCreatedBy(s2.getCreatedBy());
                                s.setCreatedDate(s2.getCreatedDate());
                            }
                        }
                        //Για τα καινούργια τραγούδια θέτει τα πεδία createdDate, createdBy
                        List<Song> created = new ArrayList<>();
                        for (Song s : this.songList) {
                            if (s.getSongId() == null) {
                                created.add(s);
                            }
                        }
                        General.setCreated(created);
                        //Αφαιρεί τα διαγραμμένα τραγούδια από το p. context
                        //(Περνάμε στην παράμετρο του remove το managed αντικείμενο με merge - την πρώτη φορά που θα
                        //πατηθεί αποθήκευση θα είναι managed αλλά αν κάτι δεν παέι καλά θα γίνει ditached)
                        for (Song old : this.oldSongList) {
                            if (!this.songList.contains(old)) {
                                this.caller.getEM().remove(this.caller.getEM().merge(old));
                            }
                        }
                    } catch (Exception e) {
                        General.showErrorMessage(e.getMessage(), "Error", this);
                        return;
                    }
                    Album a;
                    try {
                        a = this.caller.getEM().merge(this.album);
                    } catch (Exception e) {
                        General.showErrorMessage(e.getMessage(), "Error", this);
                        return;
                    }
                    try {
                        General.updateDB(this.caller.getEM());
                        this.caller.getEntityList().set(General.getSelectedRowModelIndex(this.caller.getTable()), a);
                    } catch (Exception ex) {
                        General.safeRollback(this.caller.getEM());
                        // Αν το a δεν υπάρχει στο p. context (λογικά μόνο αν έγινε ditached με το rollback)
                        if (a != null && !this.caller.getEM().contains(a)) {
                            //ξαναπαίρνουμε την managed εκδοχή της εγγραφής πριν τις αλλαγές που έκανε ο χρήστης
                            a = this.caller.getEM().find(Album.class, a.getAlbumId());
                            if (a == null) {//θα έπρεπε να μην είναι null αφού έχουμε update ήδη υπάρχουσας εγγραφής
                                General.showErrorMessage("Άγνωστο πρόβλημα με τη βάση δεδομένων.Η εφαρμογή θα κλείσει/n"
                                        + "προκειμένου να αποκλειστεί η πιθανότητα απώλειας ή αλλοίωσης δεδομένων", "Error", this);
                                System.exit(1);
                            }
                            //Τελικά επαναφέρουμε της εγγραφή της προηγούμενης φόρμας του πίνακα άλμπουμ
                            //στην managed εκδοχή πριν τις αλλαγές του χρήστη
                            int index2 = this.caller.getEntityList().indexOf(this.album);
                            this.caller.getEntityList().set(index2, a);
                        }
                        //Αν είναι σφάλμα παραβίασης περιορισμών βάσης εμφανίζει το ανάλογο μήνυμα, αν όχι το μήνυμα της excetpion αυτούσιο
                        General.showDbErrorMsgIf(ex, this);
                        return;
                    }
                    break;
                default:
                    break;
            }
            this.caller.enableDeleteUpdateIf();
            this.caller.disableDeleteUpdateIf();
        } catch (Exception e) {
            General.showErrorMessage(e.getMessage(), "Error", this);
        }
        this.caller.enableDeleteUpdateIf();
        this.caller.disableDeleteUpdateIf();
        General.closeWindowX(this);
    }//GEN-LAST:event_savejButton2ActionPerformed

    private void albumTitlejTextField1KeyPressed(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_albumTitlejTextField1KeyPressed
        if (evt.getKeyCode() == VK_ENTER) {
            this.jComboBox1.requestFocus();
        }
    }//GEN-LAST:event_albumTitlejTextField1KeyPressed

    private void jComboBox1KeyPressed(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_jComboBox1KeyPressed
        if (evt.getKeyCode() == VK_ENTER) {
            this.jComboBox2.requestFocus();
        }
    }//GEN-LAST:event_jComboBox1KeyPressed

    private void jComboBox2KeyPressed(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_jComboBox2KeyPressed
        if (evt.getKeyCode() == VK_ENTER) {
            this.diskNumberjTextField3.requestFocus();
        }
    }//GEN-LAST:event_jComboBox2KeyPressed

    private void diskNumberjTextField3KeyPressed(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_diskNumberjTextField3KeyPressed
        if (evt.getKeyCode() == VK_ENTER) {
            this.jComboBox3.requestFocus();
        }
    }//GEN-LAST:event_diskNumberjTextField3KeyPressed

    private void jComboBox3KeyPressed(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_jComboBox3KeyPressed
        if (evt.getKeyCode() == VK_ENTER) {
            this.releaseDateTextField.requestFocus();
        }
    }//GEN-LAST:event_jComboBox3KeyPressed

    private void releaseDateTextFieldKeyPressed(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_releaseDateTextFieldKeyPressed
        if (evt.getKeyCode() == VK_ENTER) {
            this.albumTitlejTextField1.requestFocus();
        }
    }//GEN-LAST:event_releaseDateTextFieldKeyPressed

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        /* Set the Nimbus look and feel */
        //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
        /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
         * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html 
         */
        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException ex) {
            java.util.logging.Logger.getLogger(ManageAlbumTableJFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            java.util.logging.Logger.getLogger(ManageAlbumTableJFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            java.util.logging.Logger.getLogger(ManageAlbumTableJFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(ManageAlbumTableJFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        //</editor-fold>
        //</editor-fold>

        /* Create and display the form */
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new ManageAlbumTableJFrame().setVisible(true);
            }
        });
    }

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.persistence.EntityManager RadioStationPUEntityManager;
    private javax.swing.JTextField albumTitlejTextField1;
    private java.util.List<Model.Albumtype> albumtypeList;
    private javax.persistence.Query albumtypeQuery;
    private java.util.List<Model.Artist> artistList;
    private javax.persistence.Query artistQuery;
    private javax.swing.JButton canceljButton1;
    private javax.swing.JLabel diskNumValidationJLabel;
    private javax.swing.JTextField diskNumberjTextField3;
    private javax.swing.JButton jButton2;
    private javax.swing.JButton jButton3;
    private javax.swing.JComboBox jComboBox1;
    private javax.swing.JComboBox jComboBox2;
    private javax.swing.JComboBox jComboBox3;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JLabel jLabel4;
    private javax.swing.JLabel jLabel5;
    private javax.swing.JLabel jLabel6;
    private javax.swing.JLabel jLabel7;
    private javax.swing.JLabel jLabel8;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JPanel jPanel2;
    private javax.swing.JPanel jPanel3;
    private javax.swing.JScrollPane jScrollPane2;
    private javax.swing.JTable jTable1;
    private java.util.List<Model.Musicgroup> musicgroupList;
    private javax.persistence.Query musicgroupQuery;
    private java.util.List<Model.Musicproductioncompany> musicproductioncompanyList;
    private javax.persistence.Query musicproductioncompanyQuery;
    private javax.swing.JTextField releaseDateTextField;
    private javax.swing.JLabel releaseDateValidationJLabel;
    private javax.swing.JButton savejButton2;
    private javax.swing.JLabel titlosValidationJLabel;
    private org.jdesktop.beansbinding.BindingGroup bindingGroup;
    // End of variables declaration//GEN-END:variables

    @Override
    public void setFormData() {
        this.albumTitlejTextField1.setText(this.album.getAlbumTitle());
        General.selectIndexIfItemToStringEquals(jComboBox1, this.album.getTypeId().toString());
        General.selectIndexIfItemToStringEquals(jComboBox2, this.album.getCompanyId().toString());
        this.diskNumberjTextField3.setText(this.album.getDiskNumber().toString());
        if (this.caller.getIsArtistAlbum()) {
            General.selectIndexIfItemToStringEquals(jComboBox3, this.album.getArtistId().toString());
        } else {
            General.selectIndexIfItemToStringEquals(jComboBox3, this.album.getMusicGroupId().toString());
        }
        this.releaseDateTextField.setText(General.dateFormater.format(this.album.getReleaseDate()));
    }

    @Override
    public boolean setEntiyFromFormData() {
        this.album.setAlbumTitle(this.albumTitlejTextField1.getText());
        this.album.setTypeId((Albumtype) this.jComboBox1.getSelectedItem());
        this.album.setCompanyId((Musicproductioncompany) this.jComboBox2.getSelectedItem());
        this.album.setDiskNumber(Integer.parseInt(this.diskNumberjTextField3.getText()));
        if (this.caller.getIsArtistAlbum()) {
            this.album.setArtistId((Artist) this.jComboBox3.getSelectedItem());
        } else {
            this.album.setMusicGroupId((Musicgroup) this.jComboBox3.getSelectedItem());
        }
        try {
            this.album.setReleaseDate(General.dateFormater.parse(this.releaseDateTextField.getText()));
        } catch (Exception ex) {
            General.showErrorMessage(ex.getMessage(), "Error", this);
            return false;
        }
        if (this.actionType == General.ActionType.Insert) {
            this.album.setCreatedBy(General.strUserName);
            this.album.setCreatedDate(new Date());
        }
        return true;
    }

    @Override
    public Frame getCaller() {
        return this.caller;
    }

    @Override
    public Frame getNext() {
        return this.next;
    }

    @Override
    public void setCallersNextNull() {
        this.caller.setNext(null);
    }

    @Override
    public void setNext(Frame w) {
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    }

}
